using AutoMapper;
using Microsoft.EntityFrameworkCore;
using NLog.Web;
using System.Reflection;
using WMS_Goodsinfo.Api.Write;
using WMS_Goodsinfo.Api.Write.Hubs;
using WMS_Goodsinfo.Api.Write.Services;
using WMS_Goodsinfo.Infastructure;
using WMS_Goodsinfo.Infastructure.Interface;
using WMS_Goodsinfo.Infastructure.Implement;
using Serilog.Events;
using Serilog.Sinks.Elasticsearch;
using Serilog;
using Consul;
using Com.Ctrip.Framework.Apollo;
using Microsoft.Extensions.Primitives;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();

builder.Services.AddSwaggerGen(x => x.IncludeXmlComments(AppContext.BaseDirectory + "WMS_Goodsinfo.Api.Write.xml", true));


//日志
//builder.Host.UseNLog();
//EF上下文
builder.Services.AddScoped(typeof(IProductRepository<>), typeof(ProductRepository<>));
//连接字符串
//builder.Services.AddDbContext<ProductDbContext>(x => x.UseSqlServer(builder.Configuration.GetConnectionString("constr")));
//中介者
builder.Services.AddMediatR(x => x.RegisterServicesFromAssemblies(Assembly.GetExecutingAssembly()));
//预测服务
builder.Services.AddScoped<IPredictionService, PredictionService>();
//仪表板统计服务
builder.Services.AddScoped<IDashboardStatisticsService, DashboardStatisticsService>();
//SignalR服务
builder.Services.AddSignalR();
//仪表板实时推送后台服务
builder.Services.AddHostedService<DashboardRealtimeService>();
//AutoMapper
builder.Services.AddAutoMapper(typeof(AutoMapperprofile));


#region   ELK日志

var configuration = builder.Configuration;
// 配置Serilog
var elaUri = configuration["ELK:ElaticSearchUrl"];
var userName = configuration["ELK:UserName"];
var password = configuration["ELK:Password"];
Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Information()
    .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
    .Enrich.FromLogContext()
    .Enrich.WithMachineName()
    .Enrich.WithThreadId()
    .Enrich.WithProcessId()
    .WriteTo.Console(new Serilog.Formatting.Compact.CompactJsonFormatter())
    .WriteTo.File("logs/goodsinfowrite-.txt",
        rollingInterval: RollingInterval.Day,
        outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}")
    .WriteTo.Elasticsearch(new ElasticsearchSinkOptions(new Uri(elaUri))
    {
        IndexFormat = "goodsinfowrite-logs-{0:yyyy.MM.dd}",
        AutoRegisterTemplate = true,
        AutoRegisterTemplateVersion = AutoRegisterTemplateVersion.ESv7,
        ModifyConnectionSettings = conn => conn.BasicAuthentication(userName, password),
        BufferBaseFilename = "./logs/serilog-buffer",
        Period = TimeSpan.FromSeconds(2)
    })
    .CreateLogger();

builder.Host.UseSerilog();


#endregion


#region  Consul

static void RegisterConsul()
{
    try
    {
        var consulClient = new ConsulClient(p => {
            p.Address = new Uri("http://123.56.75.137:8500");//主机ip:8500
        });
        // 2. 确保健康检查端点可访问
        var httpCheck = new AgentServiceCheck()
        {
            DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),
            Interval = TimeSpan.FromSeconds(10),
            HTTP = "http://123.56.75.137:8006/WeatherForecast", // 确认此端口服务是否运行
            Timeout = TimeSpan.FromSeconds(5)
        };
        // 3. 添加标签方便识别
        var registration = new AgentServiceRegistration()
        {
            Checks = new[] { httpCheck },
            ID = $"goodswrite-{Guid.NewGuid()}", // 更易读的ID
            Name = "goodswrite",                // 必须小写
            Address = "123.56.75.137",                   // 纯IP正确
            Port = 8006,                               // 端口与健康检查一致
            Tags = new[] { "dotnet-service" }           // 添加标签
        };

        // 4. 添加错误处理
        var result = consulClient.Agent.ServiceRegister(registration).Result;
        Console.WriteLine($"服务注册成功! Status: {result.StatusCode}");
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Consul注册失败: {ex.Message}");
    }
}


#endregion


#region  Apollo

builder.Configuration
    .AddApollo(builder.Configuration.GetSection("Apollo"))
    .AddDefault()
    .AddNamespace("ClientService");


builder.Services.AddDbContext<ProductDbContext>((serviceProvider, options) =>
{
    var configuration = serviceProvider.GetRequiredService<IConfiguration>();

    // 获取数据库连接字符串
   // var localConnectionString = configuration.GetConnectionString("conn");
    var apolloConnectionString = configuration.GetValue<string>("scgoods");

    //var connectionString = !string.IsNullOrEmpty(localConnectionString)
    //    ? localConnectionString
    //    : apolloConnectionString ?? string.Empty;

    options.UseSqlServer(apolloConnectionString);
});

#endregion

var app = builder.Build();

// 配置Apollo热更新监听
if (app.Configuration is IConfigurationRoot configRoot)
{
    ChangeToken.OnChange(
        () => configRoot.GetReloadToken(),
        () => Console.WriteLine($"配置已更新: {app.Configuration.GetValue<string>("scgoods")}"));
}

RegisterConsul();


//跨域 - SignalR需要支持Credentials
app.UseCors(x => x.AllowAnyHeader().AllowAnyMethod().SetIsOriginAllowed(_ => true).AllowCredentials());

// Configure the HTTP request pipeline.
//if (app.Environment.IsDevelopment())
//{
    app.UseSwagger();
    app.UseSwaggerUI();
//}

app.UseAuthorization();

app.MapControllers();

//配置SignalR Hub路由
app.MapHub<DashboardRealtimeHub>("/dashboardRealtimeHub");

app.Run();
